
#include <nuttx/config.h>
#include "EthIf.h"
#include "cdefs.h"
#include "EthTrcv_GeneralTypes.h"
#include <Mcal.h>
#include <Mcu.h>
#include "debug.h"
#include "Eth.h"
#include "dwmac.h"
#include "Mcu_Soc.h"
#include "RegHelper.h"
#include "EthDesc.h"
#include "Mcal_Delay.h"
#include "EthTrcv.h"
#include "dwmac_common.h"
#if defined(E3650)
#include "irq_num.h"
#endif
#include "Eth_PBCfg.h"

#ifdef CONFIG_NODE_MAC_ADDRESS
#define DEFAULT_MAC_ADDR (CONFIG_NODE_MAC_ADDRESS)
#else
#define DEFAULT_MAC_ADDR (0x123456789ABCu)
#endif

extern FUNC(void, ETHIF_CODE) ethif_rxindication(uint8 ctrl_idx, eth_frame_type frame_type,
    boolean is_broadcast, const uint8 *phys_addr_ptr, eth_data_type *data_ptr, uint16 len_byte);
extern FUNC(void, ETHIF_CODE) ethif_txconfirmation(uint8 ctrl_idx, eth_buf_idx_type buf_idx);
 

typedef void (*EthIf_RxCallBack_t)(uint8, Eth_FrameType, boolean, uint8 *, Eth_DataType *, uint16);
typedef void (*EthIf_TxCallBack_t)(uint8, Eth_BufIdxType);

static EthIf_RxCallBack_t Demo_RxCallBack  _SECTION(.dma_buffer);
static EthIf_TxCallBack_t Demo_TxCallBack  _SECTION(.dma_buffer);

#define ETH_START_SEC_CONST_UNSPECIFIED
#include "Eth_MemMap.h"

static CONST(Eth_EgressFifoType, ETH_CONST) tEth_EgressFifo_Config_0[2] = {
    {
        .FifoBufLenByte =128U,
        .FifoBufTotal =50U,
        .FifoIdx = 1U,
        .BufSize =  6400U,
    },
    {
        .FifoBufLenByte =1600U,
        .FifoBufTotal =2U,
        .FifoIdx = 0U,
        .BufSize =  3200U,
    },
};

static CONST(Eth_IngressFifoType, ETH_CONST) tEth_IngressFifo_Config_0[1] = {
    {
        .FifoBufLenByte =1600U,
        .FifoBufTotal =8U,
        .FifoIdx = 0U,
        .BufSize =  12800U,
    },
};

static CONST(Eth_EgressQueueCBSType, ETH_CONST) tEth_EgressQueueCbs_Config_0[ETH_MAX_DMA_CHANNEL] = {
    0
};

CONST(Eth_CntrlConfigType, ETH_CONST) tEthControlConfig_Core0[1] = {
    {
        .MACAddrLow = (DEFAULT_MAC_ADDR >> 16) & 0xFFFFFFFF, /**< First 32 bits of MAC address */
        .MACAddrHigh = DEFAULT_MAC_ADDR & 0xFFFF,/**< last 32 bits of MAC address */
        .SocCtrlIdx = ETH1,
        .MacLayerSpeed = ETH_MAC_LAYER_SPEED_1G,
        .MacLayerType = ETH_MAC_LAYER_TYPE_XGMII,
        .MacLayerSubType = REDUCED,
        .Mtu = 1536U,
        .EnableRxInterrupt = (boolean)TRUE,
        .EnableTxInterrupt = (boolean)TRUE,
        .EnableRxcDelay = (boolean)FALSE,
        .EnableTxcDelay = (boolean)FALSE,
        .MiiSupport = (boolean)TRUE,
        .EthCtrlIdx = 0U,
        .EgressFifoNumber = sizeof(tEth_EgressFifo_Config_0)/sizeof(Eth_EgressFifoType),
        .IngressFifoNumber =  sizeof(tEth_IngressFifo_Config_0)/sizeof(Eth_IngressFifoType),
        .IngressFifoConfig = (Eth_IngressFifoType*)tEth_IngressFifo_Config_0,
        .EgressFifoConfig = (Eth_EgressFifoType*)tEth_EgressFifo_Config_0,
        .rxfilter = ALL_RX_PACKET,
        .ptp_mode = PTP_MASTER,
        .ptp_version = PTP_V2,
        .TxTrafficAlgorithms = MTL_TX_ALGORITHM_SP,
        .TrafficShaper = MTL_QUEUE_MODE_AVB,
        .MtlQueueMemPolicy = MTL_MEM_POLICY_DEFAULT,
        .CbsCfg = tEth_EgressQueueCbs_Config_0,
    },
};
CONST(Eth_CoreConfigType, ETH_CONST) tEthCoreControlConfig_Core0 = {
    .EthCntrlConfigPtr = tEthControlConfig_Core0,
    .EthMaxControllers = 1,
};

CONST(Eth_ConfigType, ETH_CONST) tEth_Control_Config = {
    .EthCoreConfig={
        &tEthCoreControlConfig_Core0,
        NULL_PTR,
        NULL_PTR,
        NULL_PTR,
        NULL_PTR,
    }
};

#define ETH_STOP_SEC_CONST_UNSPECIFIED
#include "Eth_MemMap.h"

void setup_ethif_callback_funciton(void)
{
    /*PRQA S 0307 2*/
    Demo_RxCallBack = (EthIf_RxCallBack_t)&ethif_rxindication;
    Demo_TxCallBack = (EthIf_TxCallBack_t)&ethif_txconfirmation;
}

FUNC(void, ETHIF_CODE)EthIf_RxIndication(VAR(uint8, AUTOMATIC) CtrlIdx, \
        VAR(Eth_FrameType, AUTOMATIC) FrameType, \
        VAR(boolean, AUTOMATIC) IsBroadcast, \
        P2VAR(uint8, AUTOMATIC, AUTOMATIC) PhysAddrPtr, \
        P2VAR(Eth_DataType, AUTOMATIC, AUTOMATIC) DataPtr, \
        VAR(uint16, AUTOMATIC) LenByte)
{
    if (Demo_RxCallBack) {
        Demo_RxCallBack(CtrlIdx, FrameType, IsBroadcast, PhysAddrPtr, DataPtr, LenByte);
    }
}



FUNC(void, ETHIF_CODE)EthIf_TxConfirmation(VAR(uint8, AUTOMATIC) CtrlIdx, \
        VAR(Eth_BufIdxType, AUTOMATIC) BufIdx, \
        VAR(Std_ReturnType, AUTOMATIC) Result)
{
    (void) Result;
    if(Demo_TxCallBack)
        Demo_TxCallBack(CtrlIdx,BufIdx);
}


FUNC(void, ETHIF_CODE)EthIf_CtrlModeIndication( \
        VAR(uint8, AUTOMATIC) CtrlIdx, \
        VAR(Eth_ModeType, AUTOMATIC) CtrlMode \
                                              )
{
}

FUNC(void, DEM_CODE) Dem_SetEventStatus(Dem_EventIdType EventId,Dem_EventStatusType EventStatus)
{}

#ifndef CONFIG_MODULE_DET
FUNC(Std_ReturnType, DET_CODE) Det_ReportError(
    VAR(uint16, AUTOMATIC) ModuleId,
    VAR(uint8, AUTOMATIC) InstanceId,
    VAR(uint8, AUTOMATIC) ApiId,
    VAR(uint8, AUTOMATIC) ErrorId
)
{
    return 0;
}
#endif

void eth_gethmac_init(void)
{
    uint8 CtrlIdx = 0, Trcvidx = 0;

    Eth_Init(&tEth_Control_Config);

    for (CtrlIdx = 0; CtrlIdx < ETH_MAXCTRLS_SUPPORTED; CtrlIdx++) {
        if (E_OK != Eth_SetControllerMode(CtrlIdx, ETH_MODE_ACTIVE)) {
            return;
        }

        EthTrcv_Init((const EthTrcv_ConfigType *)&EthTrcv_Config);

        for (Trcvidx = 0; Trcvidx < ETHTRCV_MAXTRCV_SUPPORTED; Trcvidx++) {
            if (E_OK != EthTrcv_SetTransceiverMode(Trcvidx, ETHTRCV_MODE_ACTIVE)) {
                return;
            }
        }

        setup_ethif_callback_funciton();

        uint8 multi_cast_l2_gptp[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};   
        if (E_OK != Eth_UpdatePhysAddrFilter(CtrlIdx, multi_cast_l2_gptp, ETH_ADD_TO_FILTER)) {
            return;
        }
    }
}


void eth_enable_eth_mac(void)
{
}